// poj2486
// 题意：给定n(<=100)个节点的树，每个节点有若干数量的苹果，现在你从1号节点
//       出发，可以走k(<=200)步，每步都是向相邻节点移动一条边，到一个节点
//       就把这个节点的苹果都吃掉，不再恢复。你可以往回走，问现在你最多可以
//       走k步从1出发可以吃到最多多少个苹果。
//
// 题解：树形dp，状态很好想就是f[i][j]表示在i这个节点往子树走j步最多可以获
//       得多少苹果。
//
//       我们按照dfs的顺序处理每个节点，然后对于每个节点我们做一个类似
//       背包的dp，枚举当前要走的儿子分支v的步数，
//       f[i][j][0] = max{f[i][j - t][1] + f[v][t - 1][0], f[i][j - t][0] + f[v][t - 2][1]}
//       f[i][j][1] = max{f[i][j - t][1] + f[v][t - 1][1]}
//       然后注意一些转移时候的细节。转移的时候有点像完全背包那样，
//       利用之前的状态，所以需要从后往前转移。可以参考代码。
//       
// run: $exec < input
#include <iostream>
#include <cstring>

int const maxn = 107;
int const maxk = 207;
int head[maxn], end_point[2 * maxn], next[2 * maxn];
int alloc = 2;
int f[maxn][maxk][2];
int da[maxn];
int n, k;

void add_edge(int u, int v)
{
	end_point[alloc] = v; next[alloc] = head[u]; head[u] = alloc++;
	end_point[alloc] = u; next[alloc] = head[v]; head[v] = alloc++;
}

void init()
{
	std::memset(head, 0, sizeof(head));
	alloc = 2;
}

void dp(int u, int parent)
{
	for (int i = 0; i <= k; i++) f[u][i][0] = f[u][i][1] = da[u];
	for (int p = head[u]; p; p = next[p]) {
		int v = end_point[p];
		if (v == parent) continue;
		dp(v, u);
		for (int i = k; i >= 1; i--)
			for (int j = 1; j <= i; j++) {
				int tmp1 = f[u][i - j][1] + f[v][j - 1][0];
				if (j == 1)
					f[u][i][0] = std::max(f[u][i][0], tmp1);
				else {
					int tmp2 = f[u][i - j][0] + f[v][j - 2][1];
					f[u][i][1] = std::max(f[u][i][1], f[u][i - j][1] + f[v][j - 2][1]);
					f[u][i][0] = std::max(f[u][i][0], std::max(tmp1, tmp2));
				}
			}
	}
}

int main()
{
	std::ios::sync_with_stdio(false);
	while (std::cin >> n >> k) {
		init();
		for (int i = 1; i <= n; i++)
			std::cin >> da[i];
		for (int i = 1, x, y; i < n; i++) {
			std::cin >> x >> y;
			add_edge(x, y);
		}
		dp(1, -1);
		std::cout << f[1][k][0] << '\n';
	}
}

